package com.tbb.app.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbb.app.base.controller.MessageEndpoint;
import com.tbb.app.base.entity.Message;
import com.tbb.app.base.entity.User;
import com.tbb.app.base.mapper.MessageMapper;
import com.tbb.app.base.search.MessageAdminPageSearch;
import com.tbb.app.base.search.MessagePageSearch;
import com.tbb.app.base.service.IMessageService;
import com.tbb.app.base.service.IUserService;
import com.tbb.app.base.vo.MessageAdminVO;
import com.tbb.app.base.vo.MessageVO;
import com.tbb.app.common.service.CurrentLoginUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 消息表 服务实现类
 *
 * @author Liu
 * @since 2022-01-11
 */
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements IMessageService {

    @Autowired
    private IUserService iUserService;
    @Autowired
    private CurrentLoginUserService currentLoginUserService;

    @Override
    public IPage<MessageVO> page(MessagePageSearch search) {

        List<String> userIds = new ArrayList<>();
        userIds.add(currentLoginUserService.getUserId(true));
        userIds.add(search.getUserId());

        IPage<Message> page = new Page<>(search.getCurrentPage(), search.getPageSize());
        QueryWrapper<Message> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(Message::getCreateTime)
                .in(Message::getReceiveUserId, userIds)
                .in(Message::getSendUserId, userIds);

        return this.page(page, wrapper).convert(MessageVO::new);
    }

    @Override
    public IPage<MessageAdminVO> page(MessageAdminPageSearch search) {

        IPage<Message> page = new Page<>(search.getCurrentPage(), search.getPageSize());
        QueryWrapper<Message> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(Message::getCreateTime);
        if (search.getStartTime() != null) {
            wrapper.lambda().ge(Message::getCreateTime, search.getStartTime());
        }
        if (search.getEndTime() != null) {
            wrapper.lambda().le(Message::getCreateTime, search.getEndTime());
        }

        if (!StringUtils.isEmpty(search.getSendName()) || !StringUtils.isEmpty(search.getSendAccount())) {
            List<String> userIds = iUserService.listByNameAndAccount(search.getSendName(), search.getSendAccount());
            if (CollectionUtils.isEmpty(userIds)) {
                return new Page<>(search.getCurrentPage(), search.getPageSize());
            } else {
                wrapper.lambda().in(Message::getSendUserId, userIds);
            }
        }
        if (!StringUtils.isEmpty(search.getReceiveName()) || !StringUtils.isEmpty(search.getReceiveAccount())) {
            List<String> userIds = iUserService.listByNameAndAccount(search.getReceiveName(), search.getReceiveAccount());
            if (CollectionUtils.isEmpty(userIds)) {
                return new Page<>(search.getCurrentPage(), search.getPageSize());
            } else {
                wrapper.lambda().in(Message::getReceiveUserId, userIds);
            }
        }

        IPage<Message> result = this.page(page, wrapper);
        if (CollectionUtils.isEmpty(result.getRecords())) {
            return new Page<>(search.getCurrentPage(), search.getPageSize());
        } else {
            List<String> userIds = new ArrayList<>();
            result.getRecords().forEach(m -> {
                userIds.add(m.getReceiveUserId());
                userIds.add(m.getSendUserId());
            });
            Map<String, User> userMap = iUserService.listByIds(userIds).stream().collect(Collectors.toMap(User::getId, Function.identity()));
            return result.convert(m -> {
                MessageAdminVO vo = new MessageAdminVO();
                vo.setId(m.getId())
                        .setSendName(userMap.getOrDefault(m.getSendUserId(), new User()).getName())
                        .setSendAccount(userMap.getOrDefault(m.getSendUserId(), new User()).getAccount())
                        .setReceiveName(userMap.getOrDefault(m.getReceiveUserId(), new User()).getName())
                        .setReceiveAccount(userMap.getOrDefault(m.getReceiveUserId(), new User()).getAccount())
                        .setText(m.getText())
                        .setTime(m.getCreateTime());
                return vo;
            });
        }
    }

    @Override
    public void sendMessage(MessageVO vo) throws IOException {
        Message message = new Message();
        message.setText(vo.getText())
                .setSendUserId(vo.getSendId())
                .setReceiveUserId(vo.getReceiveId());
        this.save(message);
        vo.setId(message.getId());
        MessageEndpoint.sendMessage(vo);
    }
}
